#pragma once

#include "shape.h"
#include "material.h"

namespace kp {
	
	class Primitive;
	
	struct Intersection {
		Point3f hitp;
		Normal Ng, Ns;
		Vec2f uv;

		const Primitive* primitive = nullptr;
		const Shape* shape = nullptr;
		const Material* material = nullptr;
		Ref<BSDF> bsdf = nullptr;

		Intersection() { bsdf = MakeRef<BSDF>(); }
	};

	class Primitive {
	public:
		Primitive()	
		{}

		virtual bool Intersect(const Ray& r, Intersection& rec) const = 0;
		virtual Ref<Material> getMaterial() const = 0;
		virtual void ComputeScatteringFunctions(Intersection* si,
			TransportMode mode, bool allowMultipleLobes) const = 0;
		virtual BBox3f getBound() const = 0;
	};

	class GeometryPrimitive : public Primitive {
	public:
		GeometryPrimitive(Ref<Material> material, Ref<Shape> shape)
			: material(material), shape(shape)
		{}

		virtual bool Intersect(const Ray& r, Intersection& rec) const override;

		virtual Ref<Material> getMaterial() const override { return material; }

		virtual void ComputeScatteringFunctions(Intersection* si,
			TransportMode mode, bool allowMultipleLobes) const override;

		virtual BBox3f getBound() const override {
			return shape->GetBBox();
		}
	private:
		Ref<Shape> shape;
		Ref<Material> material;

	};

}

